package cn.kai.basic.service.impl;

import cn.kai.basic.config.BussinessException;
import cn.kai.basic.constant.BaseConstant;
import cn.kai.basic.service.IVerifyCodeService;
import cn.kai.basic.util.StrUtils;
import cn.kai.basic.util.VerifyCodeUtils;
import cn.kai.basic.vo.RegisterVo;
import cn.kai.basic.vo.RegisterVoEmail;
import cn.kai.user.domain.User;
import cn.kai.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class VerifyCodeServiceimpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IUserService userService;

    @Override
    public String graph(String uuid) {
        /*我来鹅城只办三件事*/
        //1.随机动态码
        String code = StrUtils.getComplexRandomString(4);
        //2.将uuid和动态码存到Redis，并且（uuid作为key）
        redisTemplate.opsForValue().set(uuid,code,3, TimeUnit.MINUTES);
        //3.将动态码转换成base64图形码返回前端
        return VerifyCodeUtils.VerifyCode(100,35,code);
    }

    /**
     * 手机注册验证码校验
     */
    @Override
    public void smsCode(RegisterVo vo) {
        //检验非空（通过注解校验）
        //手机号格式
        String regex = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(vo.getPhone().trim());
        if (!m.matches()){
            throw new BussinessException("手机号输入错误");
        }
        if (!vo.getType().equals("binder")){
            //当前手机是否被注册
            User user = userService.findByPhone(vo.getPhone());
            if (user != null){
                throw new BussinessException("该手机号已注册");
            }
            VerificationCode(vo);
            String smsCode = VerifiCodeTimeCheck(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE,vo.getPhone()));
            log.info("(手机注册)验证码为：{}",smsCode);
            //SmsUtils.sendMsg(vo.getPhone(),"你好：你的验证码为：\"+smsCode+\"，3分钟内有效！");//发送短信
        } else {
            String smsCode = VerifiCodeTimeCheck(String.format(BaseConstant.VerfityCodeCons.BINDER_SMSCODE_PHONE,vo.getPhone()));
            log.info("(手机注册)验证码为：{}",smsCode);
            //SmsUtils.sendMsg(vo.getPhone(),"你好：你的验证码为：\"+smsCode+\"，3分钟内有效！");//发送短信
        }
    }

    /**
     * 手机验证码是否超过60s
     * // redis中 key：register:smscode:phone  value：验证码:时间戳
     * @return
     */
    private String VerifiCodeTimeCheck(String redisKey) {
        String redisSmsCode  = (String) redisTemplate.opsForValue().get(redisKey);
        String smsCode = "";
        smsCode = TimeOut(redisSmsCode, smsCode);
        //存入Redis
        redisTemplate.opsForValue().set(redisKey,smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
        return smsCode;
    }

    /**
     * 判断是否超时，返回验证码
     * @param redisSmsCode
     * @param smsCode
     * @return
     */
    private String TimeOut(String redisSmsCode, String smsCode) {
        if (StringUtils.isNotBlank(redisSmsCode)){
            // 验证码:时间戳（非空）
            String[] split = redisSmsCode.split(":");
            Long oldTime = Long.valueOf(split[1]);
            Long nowTime = System.currentTimeMillis();
            if (nowTime-oldTime < 60 * 1000){
                throw new BussinessException("请稍后获取手机验证码");
            }
        }
        //没有验证码和时间戳
        //生成验证码
        smsCode = StrUtils.getRandomString(6);
        return smsCode;
    }

    /**
     * 邮箱验证码是否超过60s
     * @param vo
     * @return
     */
    private String VerifiCodeTimeCheck(RegisterVoEmail vo) {
        String redisSmsCode  = (String) redisTemplate.opsForValue().get(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_EMAIL, vo.getEmail()));
        String smsCode = "";
        smsCode = TimeOut(redisSmsCode, smsCode);
        //存入Redis
        redisTemplate.opsForValue().set(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_EMAIL, vo.getEmail()),
                smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
        return smsCode;
    }

    /**
     * 手机验证码是否正确
     * @param vo
     */
    private void VerificationCode(RegisterVo vo) {
        String codeValue = (String) redisTemplate.opsForValue().get(vo.getImageCodeKey());
        if (StringUtils.isBlank(codeValue) || !codeValue.equalsIgnoreCase(vo.getImageCodeValue())){ // equalsIgnoreCase不区分大小写比较
            throw new BussinessException("验证码输入不正确");
        }
    }
    /**
     * 邮箱验证码是否正确
     * @param vo
     */
    private void VerificationCode(RegisterVoEmail vo) {
        String codeValue = (String) redisTemplate.opsForValue().get(vo.getImageCodeKey());
        if (StringUtils.isBlank(codeValue) || !codeValue.equalsIgnoreCase(vo.getImageCodeValue())){ // equalsIgnoreCase不区分大小写比较
            throw new BussinessException("验证码输入不正确");
        }
    }
    /**
     * 邮箱注册验证码校验
     */
    @Override
    public void smsCodeEmail(RegisterVoEmail vo) {
        //检验非空（通过注解校验）
        //邮箱格式格式
        String regex = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(vo.getEmail().trim());
        if (!m.matches()){
            throw new BussinessException("邮箱输入错误");
        }
        //当前邮箱是否被注册
        User user = userService.findByEmail(vo.getEmail());
        if (user != null){
            throw new BussinessException("该邮箱已注册");
        }
        //验证码是否正确
        VerificationCode(vo);
        //验证码是否超过60s
        // redis中 key：register:smscode:email  value：验证码:时间戳
        String smsCode = VerifiCodeTimeCheck(vo);
        log.info("(邮箱注册)验证码为：{}",smsCode);
        //发送短信
//        SmsUtils.sendMsg(vo.getPhone(),"你好：你的验证码为：\"+smsCode+\"，5分钟内有效！");
    }

}
